home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume14 / jove4.9 / part03 < prev    next >
Encoding:
Internet Message Format  |  1988-04-25  |  53.9 KB

  1. Subject:  v14i059:  Jove, an emacs variant, version 4.9, Part03/21
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Jonathan Payne <jpayne@cs.rochester.edu>
  7. Posting-number: Volume 14, Issue 59
  8. Archive-name: jove4.9/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 3 (of 21)."
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f './Ovmakefile' -a "${1}" != "-c" ; then 
  19.   echo shar: Will not clobber existing file \"'./Ovmakefile'\"
  20. else
  21. echo shar: Extracting \"'./Ovmakefile'\" \(6758 characters\)
  22. sed "s/^X//" >'./Ovmakefile' <<'END_OF_FILE'
  23. X###########################################################################
  24. X# This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE #
  25. X# is provided to you without charge, and with no warranty.  You may give  #
  26. X# away copies of JOVE, including sources, provided that this notice is    #
  27. X# included in all the files.                                              #
  28. X###########################################################################
  29. X
  30. X# TMPDIR is where the tmp files get stored, usually /tmp or /tmp/jove.  If
  31. X# your system does not remove subdirectories of /tmp on reboot (lots do
  32. X# remove them these days) then it makes sense to make TMPDIR be /tmp/jove.
  33. X# But if you want to recover buffers on system crashes, you should create a
  34. X# directory that doesn't get clearned upon reboot, and use that instead.
  35. X# You would probably want to clean out that directory periodically with
  36. X# /etc/cron.  LIBDIR is for online documentation, the PORTSRV process,
  37. X# RECOVER, and the system-wide .joverc file.  BINDIR is where to put the
  38. X# executables JOVE and TEACHJOVE.  MANDIR is where the manual pages go for
  39. X# JOVE, RECOVER and TEACHJOVE.  MANEXT is the extension for the man pages,
  40. X# e.g., jove.1 or jove.l or jove.m.
  41. X
  42. DESTDIR =
  43. TMPDIR = /tmp
  44. LIBDIR = /usr/lib/jove
  45. BINDIR = /bin
  46. MANDIR = /usr/man/man1
  47. MANEXT = 1
  48. SHELL = /bin/csh
  49. X
  50. X# These should all just be right if the above ones are.
  51. JOVE = $(DESTDIR)$(BINDIR)/jove
  52. RECOVER = $(DESTDIR)$(LIBDIR)/recover
  53. TEACHJOVE = $(DESTDIR)$(BINDIR)/teachjove
  54. JOVERC = $(DESTDIR)$(LIBDIR)/.joverc
  55. CMDS.DOC = $(DESTDIR)$(LIBDIR)/cmds.doc
  56. TEACH-JOVE = $(DESTDIR)$(LIBDIR)/teach-jove
  57. PORTSRV = $(DESTDIR)$(LIBDIR)/portsrv
  58. JOVEM = $(DESTDIR)$(MANDIR)/jove.$(MANEXT)
  59. RECOVERM = $(DESTDIR)$(MANDIR)/recover.$(MANEXT)
  60. TEACHJOVEM = $(DESTDIR)$(MANDIR)/teachjove.$(MANEXT)
  61. X
  62. X# Select the right libraries for your system.
  63. X#    2.9BSD:    LIBS =    -ltermlib -ljobs
  64. X#    v7:    LIBS =    -ltermlib
  65. X#    4.1BSD:    LIBS =    -ltermlib -ljobs
  66. X#    4.2BSD:    LIBS =    -ltermlib
  67. X#    4.3BSD:    LIBS =    -ltermlib
  68. X
  69. OVLIBS = -lovtermcap -lovjobs
  70. LIBS = -ltermcap -ljobs
  71. X
  72. X# If you are not VMUNIX (vax running Berkeley Version 4), you must specify
  73. X# the -i flags (split I/D space) and maybe the -x option (for adb to work).
  74. X#    2.9BSD:    LDFLAGS = -x -i
  75. X#    v7:    LDFLAGS = -x -i
  76. X#    4.1BSD:    LDFLAGS =
  77. X#    4.2BSD:    LDFLAGS =
  78. X#    4.3BSD:    LDFLAGS =
  79. X
  80. LDFLAGS =  -x -i
  81. X
  82. CFLAGS = -O -V
  83. X
  84. COFLAGS = -rworking -q
  85. X
  86. BASESEG = funcdefs.o keymaps.o argcount.o ask.o buf.o ctype.o delete.o disp.o fmt.o fp.o \
  87. X      insert.o io.o jove.o malloc.o marks.o misc.o move.o re.o \
  88. X      screen.o table.o tune.o util.o version.o
  89. OVLAY1 = abbrev.o rec.o paragraph.o macros.o
  90. OVLAY2 = c.o wind.o vars.o
  91. OVLAY3 = extend.o
  92. OVLAY4 = iproc.o re1.o
  93. OVLAY5 = proc.o scandir.o term.o case.o
  94. X
  95. OBJECTS = $(BASESEG) $(OVLAY1) $(OVLAY2) $(OVLAY3) $(OVLAY4) $(OVLAY5)
  96. X
  97. C-FILES = funcdefs.c abbrev.c argcount.c ask.c buf.c c.c case.c ctype.c delete.c disp.c \
  98. X    extend.c fmt.c fp.c insert.c io.c iproc.c iproc-pipes.c iproc-ptys.c \
  99. X    jove.c macros.c malloc.c marks.c misc.c move.c paragraph.c proc.c \
  100. X    re.c re1.c rec.c scandir.c screen.c table.c term.c util.c vars.c version.c \
  101. X    wind.c
  102. X
  103. H-FILES = ctype.h io.h jove.h re.h rec.h table.h temp.h termcap.h tune.h
  104. X
  105. BACKUPS = $(C-FILES) $(H-FILES) $(DOCS) teachjove.c recover.c setmaps.c portsrv.c \
  106. X    tune.template Makefile Ovmakefile keymaps.txt README tags
  107. X
  108. DOCS =    doc/cmds.doc.nr doc/example.rc doc/jove.1 doc/jove.2 doc/jove.3 \
  109. X    doc/jove.4 doc/jove.nr doc/recover.nr doc/system.rc doc/teach-jove \
  110. X    doc/teachjove.nr doc/README
  111. X
  112. all:    xjove recover teachjove portsrv
  113. X
  114. xjove:    $(OBJECTS)
  115. X    ld $(LDFLAGS) /lib/crt0.o \
  116. X        -Z $(OVLAY1) \
  117. X        -Z $(OVLAY2) \
  118. X        -Z $(OVLAY3) \
  119. X        -Z $(OVLAY4) \
  120. X        -Z $(OVLAY5) \
  121. X        -L $(BASESEG) \
  122. X        -o xjove $(OVLIBS) -lovc
  123. X    checkobj xjove
  124. X    @-size xjove
  125. X    @-date
  126. X
  127. portsrv:    portsrv.c
  128. X    cc -o portsrv -n -O portsrv.c $(LIBS)
  129. X
  130. recover:    recover.c tune.o rec.h temp.h
  131. X    cc -o recover -n -O recover.c tune.o -ljobs
  132. X
  133. teachjove:    teachjove.c
  134. X    cc -o teachjove -n -O -DTEACHJOVE=\"$(TEACH-JOVE)\" teachjove.c
  135. X
  136. setmaps:    setmaps.c funcdefs.c
  137. X    cc -o setmaps setmaps.c
  138. X
  139. keymaps.c:    setmaps keymaps.txt
  140. X    setmaps < keymaps.txt > keymaps.c
  141. X
  142. tune.c: Makefile tune.template
  143. X    @echo "/* Changes should be made in Makefile, not to this file! */" > tune.c
  144. X    @echo "" >> tune.c
  145. X    @sed -e 's;TMPDIR;$(TMPDIR);' \
  146. X         -e 's;LIBDIR;$(LIBDIR);' \
  147. X         -e 's;BINDIR;$(BINDIR);' \
  148. X         -e 's;SHELL;$(SHELL);' tune.template >> tune.c
  149. X
  150. install: $(LIBDIR) $(TEACH-JOVE) $(CMDS.DOC) $(JOVERC) $(PORTSRV) $(RECOVER) \
  151. X     $(JOVE) $(TEACHJOVE) $(JOVEM) $(RECOVERM) $(TEACHJOVEM)
  152. X
  153. X$(DESTDIR)$(LIBDIR):
  154. X    -mkdir (DESTDIR)$(LIBDIR)
  155. X
  156. X$(TEACH-JOVE): doc/teach-jove
  157. X    install -c -m 644 doc/teach-jove $(TEACH-JOVE)
  158. X
  159. X$(CMDS.DOC): doc/cmds.doc
  160. X    install -c -m 644 doc/cmds.doc $(CMDS.DOC)
  161. X
  162. X$(JOVERC): doc/system.rc
  163. X    install -c -m 644 doc/system.rc $(JOVERC)
  164. X
  165. X$(PORTSRV): portsrv
  166. X    install -c -m 755 portsrv $(PORTSRV)
  167. X
  168. X$(RECOVER): recover
  169. X    install -c -m 755 recover $(RECOVER)
  170. X
  171. X$(JOVE): xjove
  172. X    install -c -m 755 xjove $(JOVE)
  173. X
  174. X$(TEACHJOVE): teachjove
  175. X    install -c -m 755 teachjove $(TEACHJOVE)
  176. X
  177. X$(JOVEM): doc/jove.nr
  178. X    @sed -e 's;TMPDIR;$(TMPDIR);' \
  179. X         -e 's;LIBDIR;$(LIBDIR);' \
  180. X         -e 's;SHELL;$(SHELL);' doc/jove.nr > /tmp/jove.nr
  181. X    install -m 644 /tmp/jove.nr $(JOVEM)
  182. X
  183. X$(RECOVERM): doc/recover.nr
  184. X    @sed -e 's;TMPDIR;$(TMPDIR);' \
  185. X         -e 's;LIBDIR;$(LIBDIR);' \
  186. X         -e 's;SHELL;$(SHELL);' doc/recover.nr > /tmp/recover.nr
  187. X    install -m 644 /tmp/recover.nr $(RECOVERM)
  188. X
  189. X$(TEACHJOVEM): doc/teachjove.nr
  190. X    @sed -e 's;TMPDIR;$(TMPDIR);' \
  191. X         -e 's;LIBDIR;$(LIBDIR);' \
  192. X         -e 's;SHELL;$(SHELL);' doc/teachjove.nr > /tmp/teachjove.nr
  193. X    install -m 644 /tmp/teachjove.nr $(TEACHJOVEM)
  194. X
  195. echo:
  196. X    @echo $(C-FILES) $(H-FILES)
  197. X
  198. lint:
  199. X    lint -x $(C-FILES)
  200. X    echo Done
  201. X
  202. tags:
  203. X    ctags -w $(C-FILES) $(H-FILES)
  204. X
  205. X
  206. jove.shar:
  207. X    shar $(BACKUPS) doc/* > jove.shar
  208. X
  209. backup:
  210. X    tar cf backup $(BACKUPS)
  211. X
  212. tape-backup:
  213. X    tar cbf 20 /dev/rmt0 $(BACKUPS)
  214. X
  215. clean:
  216. X    rm -f a.out core $(OBJECTS) keymaps.c xjove \
  217. X        portsrv recover setmaps teachjove
  218. X
  219. X# abbrev.o: jove.h tune.h
  220. X# ask.o: jove.h tune.h
  221. X# buf.o: jove.h tune.h
  222. X# c.o: jove.h tune.h
  223. X# delete.o: jove.h tune.h
  224. X# disp.o: jove.h tune.h termcap.h
  225. X# extend.o: jove.h tune.h
  226. X# fmt.o: jove.h tune.h termcap.h
  227. X# funcdefs.o: jove.h tune.h
  228. X# insert.o: jove.h tune.h
  229. X# io.o: jove.h tune.h termcap.h temp.h
  230. X# iproc.o: jove.h tune.h
  231. X# jove.o: jove.h tune.h termcap.h
  232. X# macros.o: jove.h tune.h
  233. X# marks.o: jove.h tune.h
  234. X# misc.o: jove.h tune.h
  235. X# move.o: jove.h tune.h
  236. X# portsrv.o: jove.h tune.h
  237. X# proc.o: jove.h tune.h
  238. X# re.o: jove.h tune.h
  239. X# rec.o: jove.h tune.h temp.h rec.h
  240. X# recover.o: jove.h tune.h temp.h rec.h
  241. X# screen.o: jove.h tune.h temp.h termcap.h
  242. X# setmaps.o: jove.h tune.h
  243. X# term.o: jove.h tune.h
  244. X# tune.o: tune.h
  245. X# util.o: jove.h tune.h
  246. X# wind.o: jove.h tune.h termcap.h
  247. END_OF_FILE
  248. if test 6758 -ne `wc -c <'./Ovmakefile'`; then
  249.     echo shar: \"'./Ovmakefile'\" unpacked with wrong size!
  250. fi
  251. # end of './Ovmakefile'
  252. fi
  253. if test -f './abbrev.c' -a "${1}" != "-c" ; then 
  254.   echo shar: Will not clobber existing file \"'./abbrev.c'\"
  255. else
  256. echo shar: Extracting \"'./abbrev.c'\" \(6522 characters\)
  257. sed "s/^X//" >'./abbrev.c' <<'END_OF_FILE'
  258. X/***************************************************************************
  259. X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  260. X * is provided to you without charge, and with no warranty.  You may give  *
  261. X * away copies of JOVE, including sources, provided that this notice is    *
  262. X * included in all the files.                                              *
  263. X ***************************************************************************/
  264. X
  265. X#include "jove.h"
  266. X
  267. X#ifdef ABBREV
  268. X
  269. X#include "io.h"
  270. X#include "ctype.h"
  271. X
  272. X#ifdef MSDOS
  273. X#include <io.h>
  274. X#endif
  275. X#define HASHSIZE    20
  276. X
  277. struct abbrev {
  278. X    unsigned int    a_hash;
  279. X    char    *a_abbrev,
  280. X        *a_phrase;
  281. X    struct abbrev    *a_next;
  282. X    data_obj    *a_cmdhook;
  283. X};
  284. X
  285. X#ifdef MAC
  286. X#    undef private
  287. X#    define private
  288. X#endif
  289. X
  290. X#ifdef    LINT_ARGS
  291. private    void
  292. X    define(struct abbrev **, char *, char *),
  293. X    def_abbrev(struct abbrev **),
  294. X    rest_abbrevs(char *),
  295. X    save_abbrevs(char *);
  296. X
  297. private    unsigned int hash(char *);
  298. private    struct abbrev * lookup(struct abbrev **, char *);
  299. X#else
  300. private    void
  301. X    define(),
  302. X    def_abbrev(),
  303. X    rest_abbrevs(),
  304. X    save_abbrevs();
  305. X
  306. private    unsigned int hash();
  307. private    struct abbrev * lookup();
  308. X#endif    /* LINT_ARGS */
  309. X
  310. X#ifdef MAC
  311. X#    undef private
  312. X#    define private static
  313. X#endif
  314. X
  315. X#define GLOBAL    NMAJORS
  316. private struct abbrev    *A_tables[NMAJORS + 1][HASHSIZE] = {0};
  317. X
  318. int AutoCaseAbbrev = 1;
  319. X
  320. private unsigned int
  321. hash(a)
  322. register char    *a;
  323. X{
  324. X    register unsigned int    hashval = 0;
  325. X    register int    c;
  326. X
  327. X    while (c = *a++)
  328. X        hashval = (hashval << 2) + c;
  329. X
  330. X    return hashval;
  331. X}
  332. X
  333. private void
  334. def_abbrev(table)
  335. struct abbrev    *table[HASHSIZE];
  336. X{
  337. X    char    abbrev[100],
  338. X        phrase[100];
  339. X
  340. X    strcpy(abbrev, ask((char *) 0, "abbrev: "));
  341. X    strcpy(phrase, ask((char *) 0, "abbrev: %s phrase: ", abbrev));
  342. X    define(table, abbrev, phrase);
  343. X}
  344. X
  345. private struct abbrev *
  346. lookup(table, abbrev)
  347. register struct abbrev    *table[HASHSIZE];
  348. register char    *abbrev;
  349. X{
  350. X    register struct abbrev    *ap;
  351. X    unsigned int    h;
  352. X
  353. X    h = hash(abbrev);
  354. X    for (ap = table[h % HASHSIZE]; ap; ap = ap->a_next)
  355. X        if (ap->a_hash == h && strcmp(ap->a_abbrev, abbrev) == 0)
  356. X            break;
  357. X    return ap;
  358. X}
  359. X
  360. private void
  361. define(table, abbrev, phrase)
  362. register struct abbrev    *table[HASHSIZE];
  363. char    *abbrev,
  364. X    *phrase;
  365. X{
  366. X    register struct abbrev    *ap;
  367. X
  368. X    ap = lookup(table, abbrev);
  369. X    if (ap == 0) {
  370. X        register unsigned int    h = hash(abbrev);
  371. X
  372. X        ap = (struct abbrev *) emalloc(sizeof *ap);
  373. X        ap->a_hash = h;
  374. X        ap->a_abbrev = copystr(abbrev);
  375. X        h %= HASHSIZE;
  376. X        ap->a_next = table[h];
  377. X        ap->a_cmdhook = 0;
  378. X        table[h] = ap;
  379. X    } else
  380. X        free(ap->a_phrase);
  381. X    ap->a_phrase = copystr(phrase);
  382. X}
  383. X
  384. void
  385. AbbrevExpand()
  386. X{
  387. X    Bufpos    point;
  388. X    char    wordbuf[100];
  389. X    register char    *wp = wordbuf,
  390. X            *cp;
  391. X#if !(defined(IBMPC) || defined(MAC))
  392. X    register int    c;
  393. X#else
  394. X    int c;
  395. X#endif    
  396. X    int    UC_count = 0;
  397. X    struct abbrev    *ap;
  398. X
  399. X    DOTsave(&point);
  400. X    WITH_TABLE(curbuf->b_major)
  401. X    b_word(1);
  402. X    while (curchar < point.p_char && ismword(c = linebuf[curchar])) {
  403. X        if (AutoCaseAbbrev) {
  404. X            if (isupper(c)) {
  405. X                UC_count += 1;
  406. X#if (defined(IBMPC) || defined(MAC))
  407. X                lower(&c);
  408. X#else
  409. X                c = tolower(c);
  410. X#endif                
  411. X            }
  412. X        }
  413. X        *wp++ = c;
  414. X        curchar += 1;
  415. X    }
  416. X    *wp = '\0';
  417. X    END_TABLE();
  418. X
  419. X    if ((ap = lookup(A_tables[curbuf->b_major], wordbuf)) == 0 &&
  420. X        (ap = lookup(A_tables[GLOBAL], wordbuf)) == 0) {
  421. X        SetDot(&point);
  422. X        return;
  423. X    }
  424. X    del_char(BACKWARD, (wp - wordbuf));
  425. X
  426. X    for (cp = ap->a_phrase; c = *cp; ) {
  427. X        if (AutoCaseAbbrev) {
  428. X            insert_c(islower(c) && UC_count &&
  429. X                   (cp == ap->a_phrase || (UC_count > 1 && (cp[-1] == ' '))) ?
  430. X                toupper(c) : c, 1);
  431. X        } else
  432. X            insert_c(c, 1);
  433. X        cp += 1;
  434. X    }
  435. X    if (ap->a_cmdhook != 0)
  436. X        ExecCmd(ap->a_cmdhook);
  437. X}
  438. X
  439. private char    *mode_names[NMAJORS + 1] = {
  440. X    "Fundamental Mode",
  441. X    "Text Mode",
  442. X    "C Mode",
  443. X#ifdef LISP
  444. X    "Lisp Mode",
  445. X#endif
  446. X    "Global"
  447. X};
  448. X
  449. private void
  450. save_abbrevs(file)
  451. char    *file;
  452. X{
  453. X    File    *fp;
  454. X    struct abbrev    *ap,
  455. X            **tp;
  456. X    char    buf[LBSIZE];
  457. X    int    i,
  458. X        count = 0;
  459. X
  460. X    fp = open_file(file, buf, F_WRITE, COMPLAIN, QUIET);
  461. X    for (i = 0; i <= GLOBAL; i++) {
  462. X        fprintf(fp, "------%s abbrevs------\n", mode_names[i]);
  463. X        for (tp = A_tables[i]; tp < &A_tables[i][HASHSIZE]; tp++)
  464. X            for (ap = *tp; ap; ap = ap->a_next) {
  465. X                fprintf(fp, "%s:%s\n",
  466. X                    ap->a_abbrev,
  467. X                    ap->a_phrase);
  468. X                count += 1;
  469. X            }
  470. X    }
  471. X    f_close(fp);
  472. X    add_mess(" %d written.", count);
  473. X}
  474. X
  475. private void
  476. rest_abbrevs(file)
  477. char    *file;
  478. X{
  479. X    int    eof = 0,
  480. X        mode = -1,    /* Will be ++'d immediately */
  481. X        lnum = 0;
  482. X    char    *phrase_p;
  483. X    File    *fp;
  484. X    char    buf[LBSIZE];
  485. X
  486. X    fp = open_file(file, buf, F_READ, COMPLAIN, QUIET);
  487. X    while (mode <= GLOBAL) {
  488. X        eof = f_gets(fp, genbuf, LBSIZE);
  489. X        if (eof || genbuf[0] == '\0')
  490. X            break;
  491. X        lnum += 1;
  492. X        if (strncmp(genbuf, "------", 6) == 0) {
  493. X            mode += 1;
  494. X            continue;
  495. X        }
  496. X        if (mode == -1)
  497. fmterr:            complain("Abbrev. format error, line %d.", file, lnum);
  498. X        phrase_p = index(genbuf, ':');
  499. X        if (phrase_p == 0)
  500. X            goto fmterr;
  501. X        *phrase_p++ = '\0';    /* Null terminate the abbrev. */
  502. X        define(A_tables[mode], genbuf, phrase_p);
  503. X    }
  504. X    f_close(fp);
  505. X    message(NullStr);
  506. X}
  507. X
  508. void
  509. DefGAbbrev()
  510. X{
  511. X    def_abbrev(A_tables[GLOBAL]);
  512. X}
  513. X
  514. void
  515. DefMAbbrev()
  516. X{
  517. X    def_abbrev(A_tables[curbuf->b_major]);
  518. X}
  519. X
  520. void
  521. SaveAbbrevs()
  522. X{
  523. X    char    filebuf[FILESIZE];
  524. X
  525. X    save_abbrevs(ask_file((char *) 0, (char *) 0, filebuf));
  526. X}
  527. X
  528. void
  529. RestAbbrevs()
  530. X{
  531. X    char    filebuf[FILESIZE];
  532. X
  533. X    rest_abbrevs(ask_file((char *) 0, (char *) 0, filebuf));
  534. X}
  535. X
  536. void
  537. EditAbbrevs()
  538. X{
  539. X    char    *tname = "jove_wam.$$$",
  540. X        *EditName = "Abbreviation Edit";
  541. X    Buffer    *obuf = curbuf,
  542. X        *ebuf;
  543. X
  544. X    if (ebuf = buf_exists(EditName)) {
  545. X        if (ebuf->b_type != B_SCRATCH)
  546. X            confirm("Over-write buffer %b?", ebuf);
  547. X    }
  548. X    SetBuf(ebuf = do_select(curwind, EditName));
  549. X    ebuf->b_type = B_SCRATCH;
  550. X    initlist(ebuf);
  551. X    /* Empty buffer.  Save the definitions to a tmp file
  552. X       and read them into this buffer so we can edit them. */
  553. X    save_abbrevs(tname);
  554. X    read_file(tname, NO);
  555. X    message("[Edit definitions and then type C-X C-C]");
  556. X    Recur();        /* We edit them ... now */
  557. X    /* RESetBuf in case we deleted the buffer while we were editing. */
  558. X    SetBuf(ebuf = do_select(curwind, EditName));
  559. X    if (IsModified(ebuf)) {
  560. X        SetBuf(ebuf);
  561. X        file_write(tname, 0);
  562. X        rest_abbrevs(tname);
  563. X        unmodify();
  564. X    }
  565. X    (void) unlink(tname);
  566. X    SetBuf(do_select(curwind, obuf->b_name));
  567. X}
  568. X
  569. void
  570. BindMtoW()
  571. X{
  572. X    struct abbrev    *ap;
  573. X    char    *word;
  574. X    data_obj    *hook;
  575. X
  576. X    word = ask((char *) 0, "Word: ");
  577. X
  578. X    if ((ap = lookup(A_tables[curbuf->b_major], word)) == 0 &&
  579. X        (ap = lookup(A_tables[GLOBAL], word)) == 0)
  580. X            complain("%s: unknown abbrev.", word);
  581. X
  582. X    hook = findmac("Macro: ");
  583. X    if (hook == 0)
  584. X        complain("[Undefined macro]");
  585. X    ap->a_cmdhook = hook;
  586. X}
  587. X
  588. X#endif /* ABBREV */
  589. END_OF_FILE
  590. if test 6522 -ne `wc -c <'./abbrev.c'`; then
  591.     echo shar: \"'./abbrev.c'\" unpacked with wrong size!
  592. fi
  593. # end of './abbrev.c'
  594. fi
  595. if test -f './delete.c' -a "${1}" != "-c" ; then 
  596.   echo shar: Will not clobber existing file \"'./delete.c'\"
  597. else
  598. echo shar: Extracting \"'./delete.c'\" \(6544 characters\)
  599. sed "s/^X//" >'./delete.c' <<'END_OF_FILE'
  600. X/***************************************************************************
  601. X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  602. X * is provided to you without charge, and with no warranty.  You may give  *
  603. X * away copies of JOVE, including sources, provided that this notice is    *
  604. X * included in all the files.                                              *
  605. X ***************************************************************************/
  606. X
  607. X/* Routines to perform all kinds of deletion.  */
  608. X
  609. X#include "jove.h"
  610. X
  611. X/* Assumes that either line1 or line2 is actual the current line, so it can
  612. X   put its result into linebuf. */
  613. X
  614. void
  615. patchup(line1, char1, line2, char2)
  616. Line    *line1,
  617. X    *line2;
  618. register int    char1,
  619. X        char2;
  620. X{
  621. X    if (line1 != line2)
  622. X        ChkWindows(line1, line2);
  623. X    DotTo(line1, char1);
  624. X    modify();
  625. X    linecopy(linebuf, curchar, lcontents(line2) + char2);
  626. X
  627. X    /* The following is a redisplay optimization. */
  628. X    if (line1 != line2 && (char1 == 0 && char2 == 0))
  629. X        line1->l_dline = line2->l_dline;
  630. X
  631. X    DFixMarks(line1, char1, line2, char2);
  632. X    makedirty(curline);
  633. X}
  634. X
  635. X/* Deletes the region by unlinking the lines in the middle,
  636. X   and patching things up.  The unlinked lines are still in
  637. X   order.  */
  638. X
  639. Line *
  640. reg_delete(line1, char1, line2, char2)
  641. Line    *line1,
  642. X    *line2;
  643. X{
  644. X    register Line    *retline;
  645. X
  646. X    if ((line1 == line2 && char1 == char2) || line2 == 0)
  647. X        complain((char *) 0);
  648. X    (void) fixorder(&line1, &char1, &line2, &char2);
  649. X
  650. X    retline = nbufline();    /* New buffer line */
  651. X
  652. X    (void) ltobuf(line1, genbuf);
  653. X    if (line1 == line2)
  654. X        genbuf[char2] = '\0';
  655. X
  656. X    retline->l_prev = 0;
  657. X    retline->l_dline = putline(&genbuf[char1]);
  658. X    patchup(line1, char1, line2, char2);
  659. X
  660. X    if (line1 == line2)
  661. X        retline->l_next = 0;
  662. X    else {
  663. X        retline->l_next = line1->l_next;
  664. X        (void) ltobuf(line2, genbuf);
  665. X        genbuf[char2] = '\0';
  666. X        line2->l_dline = putline(genbuf);
  667. X        /* Shorten this line */
  668. X    }
  669. X
  670. X    if (line1 != line2) {
  671. X        line1->l_next = line2->l_next;
  672. X        if (line1->l_next)
  673. X            line1->l_next->l_prev = line1;
  674. X        else
  675. X            curbuf->b_last = line1;
  676. X        line2->l_next = 0;
  677. X    }
  678. X
  679. X    return retline;
  680. X}
  681. X
  682. void
  683. lremove(line1, line2)
  684. register Line    *line1,
  685. X        *line2;
  686. X{
  687. X    Line    *next = line1->l_next;
  688. X
  689. X    if (line1 == line2)
  690. X        return;
  691. X    line1->l_next = line2->l_next;
  692. X    if (line1->l_next)
  693. X        line1->l_next->l_prev = line1;
  694. X    else
  695. X        curbuf->b_last = line1;
  696. X    lfreereg(next, line2);    /* Put region at end of free line list. */
  697. X}
  698. X
  699. X/* Delete character forward */
  700. X
  701. void
  702. DelNChar()
  703. X{
  704. X    del_char(FORWARD, arg_value());
  705. X}
  706. X
  707. X/* Delete character backward */
  708. X
  709. void
  710. DelPChar()
  711. X{
  712. X    if (MinorMode(OverWrite)) {
  713. X        int    count = min(arg_value(), curchar);
  714. X
  715. X        b_char(count);
  716. X
  717. X        /* overwrite with spaces */
  718. X        set_arg_value(count);
  719. X        LastKeyStruck = ' ';
  720. X        SelfInsert();
  721. X
  722. X        b_char(count);
  723. X    } else        
  724. X        del_char(BACKWARD, arg_value());
  725. X}
  726. X
  727. X/* Delete some characters.  If deleting forward then call for_char
  728. X   to the final position otherwise call back_char.  Then delete the
  729. X   region between the two with patchup(). */
  730. X
  731. void
  732. del_char(dir, num)
  733. X{
  734. X    Bufpos    before,
  735. X        after;
  736. X    int    killp = (abs(num) > 1);
  737. X
  738. X    DOTsave(&before);
  739. X    if (dir == FORWARD) f_char(num);
  740. X        else b_char(num);
  741. X    if (before.p_line == curline && before.p_char == curchar)
  742. X        complain((char *) 0);
  743. X    if (killp)
  744. X        reg_kill(before.p_line, before.p_char, 1);
  745. X    else {
  746. X        DOTsave(&after);
  747. X        (void) fixorder(&before.p_line, &before.p_char, &after.p_line, &after.p_char);
  748. X        patchup(before.p_line, before.p_char, after.p_line, after.p_char);
  749. X        lremove(before.p_line, after.p_line);
  750. X    }
  751. X}
  752. X
  753. X/* This kills a region between point, and line1/char1 and puts it on
  754. X   the kill-ring.  If the last command was one of the kill commands,
  755. X   the region is appended (prepended if backwards) to the last entry.  */
  756. X
  757. int    killptr = 0;
  758. Line    *killbuf[NUMKILLS];
  759. X
  760. void
  761. reg_kill(line2, char2, dot_moved)
  762. Line    *line2;
  763. X{
  764. X    Line    *nl,
  765. X        *line1 = curline;
  766. X    int    char1 = curchar;
  767. X    int    backwards;
  768. X
  769. X    backwards = !fixorder(&line1, &char1, &line2, &char2);
  770. X    /* This is a kludge!  But it possible for commands that don't
  771. X       know which direction they are deleting in (e.g., delete
  772. X       previous word could have been called with a negative argument
  773. X       in which case, it wouldn't know that it really deleted
  774. X       forward. */
  775. X
  776. X    if (!dot_moved)
  777. X        backwards = !backwards;
  778. X
  779. X    DotTo(line1, char1);
  780. X
  781. X    nl = reg_delete(line1, char1, line2, char2);
  782. X
  783. X    if (last_cmd != KILLCMD) {
  784. X        killptr = ((killptr + 1) % NUMKILLS);
  785. X        lfreelist(killbuf[killptr]);
  786. X        killbuf[killptr] = nl;
  787. X    } else {
  788. X        Line    *lastln = lastline(nl);
  789. X
  790. X        if (backwards)
  791. X            (void) DoYank(nl, 0, lastln, length(lastln), killbuf[killptr], 0, (Buffer *) 0);
  792. X        else {
  793. X            Line    *olastln = lastline(killbuf[killptr]);
  794. X
  795. X            (void) DoYank(nl, 0, lastln, length(lastln), olastln, length(olastln), (Buffer *) 0);
  796. X        }
  797. X    }
  798. X    this_cmd = KILLCMD;
  799. X}
  800. X
  801. void
  802. DelReg()
  803. X{
  804. X    register Mark    *mp = CurMark();
  805. X
  806. X    reg_kill(mp->m_line, mp->m_char, 0);
  807. X}
  808. X
  809. X/* Save a region.  A pretend kill. */
  810. X
  811. void
  812. CopyRegion()
  813. X{
  814. X    register Line    *nl;
  815. X    register Mark    *mp;
  816. X    register int    status;
  817. X
  818. X    mp = CurMark();
  819. X    if (mp->m_line == curline && mp->m_char == curchar)
  820. X        complain((char *) 0);
  821. X
  822. X    killptr = ((killptr + 1) % NUMKILLS);
  823. X    if (killbuf[killptr])
  824. X        lfreelist(killbuf[killptr]);
  825. X    nl = killbuf[killptr] = nbufline();
  826. X    SavLine(nl, NullStr);
  827. X    nl->l_next = nl->l_prev = 0;
  828. X
  829. X    status = inorder(mp->m_line, mp->m_char, curline, curchar);
  830. X    if (status == -1)
  831. X        return;
  832. X
  833. X    if (status)
  834. X        (void) DoYank(mp->m_line, mp->m_char, curline, curchar,
  835. X                nl, 0, (Buffer *) 0);
  836. X    else
  837. X        (void) DoYank(curline, curchar, mp->m_line, mp->m_char,
  838. X                nl, 0, (Buffer *) 0);
  839. X}
  840. X
  841. void
  842. DelWtSpace()
  843. X{
  844. X    register char    *ep = &linebuf[curchar],
  845. X            *sp = &linebuf[curchar];
  846. X
  847. X    while (*ep == ' ' || *ep == '\t')
  848. X        ep += 1;
  849. X    while (sp > linebuf && *(sp - 1) == ' ' || *(sp - 1) == '\t')
  850. X        sp -= 1;
  851. X    if (sp != ep) {
  852. X        curchar = sp - linebuf;
  853. X        DFixMarks(curline, curchar, curline, curchar + (ep - sp));
  854. X        strcpy(sp, ep);
  855. X        makedirty(curline);
  856. X        modify();
  857. X    }
  858. X}
  859. X
  860. void
  861. DelBlnkLines()
  862. X{
  863. X    register Mark    *dot;
  864. X    int    all;
  865. X
  866. X    if (!blnkp(&linebuf[curchar]))
  867. X        return;
  868. X    dot = MakeMark(curline, curchar, M_FLOATER);
  869. X    all = !blnkp(linebuf);
  870. X    while (blnkp(linebuf) && curline->l_prev)
  871. X        SetLine(curline->l_prev);
  872. X    all |= (firstp(curline));
  873. X    Eol();
  874. X    DelWtSpace();
  875. X    line_move(FORWARD, 1, NO);
  876. X    while (blnkp(linebuf) && !eobp()) {
  877. X        DelWtSpace();
  878. X        del_char(FORWARD, 1);
  879. X    }
  880. X    if (!all && !eobp())
  881. X        open_lines(1);
  882. X    ToMark(dot);
  883. X    DelMark(dot);
  884. X}
  885. X
  886. void
  887. DelNWord()
  888. X{
  889. X    dword(1);
  890. X}
  891. X
  892. void
  893. DelPWord()
  894. X{
  895. X    dword(0);
  896. X}
  897. X
  898. void
  899. dword(forward)
  900. X{
  901. X    Bufpos    savedot;
  902. X
  903. X    DOTsave(&savedot);
  904. X    if(forward)  ForWord();
  905. X        else BackWord();
  906. X    reg_kill(savedot.p_line, savedot.p_char, 1);
  907. X}
  908. END_OF_FILE
  909. if test 6544 -ne `wc -c <'./delete.c'`; then
  910.     echo shar: \"'./delete.c'\" unpacked with wrong size!
  911. fi
  912. # end of './delete.c'
  913. fi
  914. if test -f './fp.c' -a "${1}" != "-c" ; then 
  915.   echo shar: Will not clobber existing file \"'./fp.c'\"
  916. else
  917. echo shar: Extracting \"'./fp.c'\" \(7807 characters\)
  918. sed "s/^X//" >'./fp.c' <<'END_OF_FILE'
  919. X/***************************************************************************
  920. X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  921. X * is provided to you without charge, and with no warranty.  You may give  *
  922. X * away copies of JOVE, including sources, provided that this notice is    *
  923. X * included in all the files.                                              *
  924. X ***************************************************************************/
  925. X
  926. X#include "jove.h"
  927. X#include "io.h"
  928. X#include "ctype.h"
  929. X#include "termcap.h"
  930. X
  931. X#ifdef MAC
  932. X#    include "mac.h"
  933. X#else
  934. X#    include <sys/stat.h>
  935. X#    ifndef MSDOS
  936. X#        include <sys/file.h>
  937. X#    else /* MSDOS */
  938. X#        include <fcntl.h>
  939. X#        include <io.h>
  940. X#    endif /* MSDOS */
  941. X#endif /* MAC */
  942. X
  943. X#include <errno.h>
  944. X
  945. X#ifdef MAC
  946. X#    undef private
  947. X#    define private
  948. X#endif
  949. X
  950. X#ifdef    LINT_ARGS
  951. private File * f_alloc(char *, int, int, char *, int);
  952. X#ifdef RAINBOW
  953. private int rbwrite(int, char *, int);
  954. X#endif
  955. X#else
  956. private File * f_alloc();
  957. X#ifdef RAINBOW
  958. private int rbwrite();
  959. X#endif
  960. X#endif    /* LINT_ARGS */
  961. X
  962. X#ifdef MAC
  963. X#    undef private
  964. X#    define private static
  965. X#endif
  966. X
  967. X#ifndef L_SET
  968. X#    define L_SET 0
  969. X#endif
  970. X
  971. X#define MAXFILES    20    /* good enough for my purposes */
  972. X
  973. private File    _openfiles[MAXFILES] = {0};
  974. X
  975. private File *
  976. f_alloc(name, flags, fd, buffer, buf_size)
  977. char    *name,
  978. X    *buffer;
  979. X{
  980. X    register File    *fp;
  981. X    register int    i;
  982. X
  983. X    for (fp = _openfiles, i = 0; i < MAXFILES; i++, fp++)
  984. X        if (fp->f_flags == 0)
  985. X            break;
  986. X    if (i == MAXFILES)
  987. X        complain("[Too many open files!]");
  988. X    fp->f_bufsize = buf_size;
  989. X    fp->f_cnt = 0;
  990. X    fp->f_fd = fd;
  991. X    fp->f_flags = flags;
  992. X    if (buffer == 0) {
  993. X        buffer = emalloc(buf_size);
  994. X        fp->f_flags |= F_MYBUF;
  995. X    }
  996. X    fp->f_base = fp->f_ptr = buffer;
  997. X    fp->f_name = copystr(name);
  998. X
  999. X    return fp;
  1000. X}
  1001. X
  1002. void
  1003. gc_openfiles()
  1004. X{
  1005. X    register File    *fp;
  1006. X
  1007. X    for (fp = _openfiles; fp < &_openfiles[MAXFILES]; fp++)
  1008. X        if (fp->f_flags != 0 && (fp->f_flags & F_LOCKED) == 0)
  1009. X            f_close(fp);
  1010. X}
  1011. X
  1012. File *
  1013. fd_open(name, flags, fd, buffer, bsize)
  1014. char    *name,
  1015. X    *buffer;
  1016. X{
  1017. X    return f_alloc(name, flags, fd, buffer, bsize);
  1018. X}
  1019. X
  1020. File *
  1021. f_open(name, flags, buffer, buf_size)
  1022. char    *name,
  1023. X    *buffer;
  1024. X{
  1025. X    register int    fd;
  1026. X    int    mode = F_MODE(flags);
  1027. X
  1028. X    if (mode == F_READ)
  1029. X        fd = open(name, 0);
  1030. X    if (mode == F_APPEND) {
  1031. X        fd = open(name, 1);
  1032. X        if (fd == -1)
  1033. X            mode = F_WRITE;
  1034. X        else
  1035. X            (void) lseek(fd, 0L, 2);
  1036. X    }
  1037. X    if (mode == F_WRITE)
  1038. X        fd = creat(name, CreatMode);
  1039. X    if (fd == -1)
  1040. X        return NIL;
  1041. X#ifdef MSDOS
  1042. X    else
  1043. X        setmode(fd, 0x8000);
  1044. X#endif /* MSDOS */
  1045. X    return f_alloc(name, flags, fd, buffer, buf_size);
  1046. X}
  1047. X
  1048. void
  1049. f_close(fp)
  1050. File    *fp;
  1051. X{
  1052. X    flush(fp);
  1053. X#ifdef BSD4_2 
  1054. X    if (fp->f_flags & (F_WRITE|F_APPEND))
  1055. X        (void) fsync(fp->f_fd);
  1056. X#endif 
  1057. X    (void) close(fp->f_fd);
  1058. X    if (fp->f_flags & F_MYBUF)
  1059. X        free(fp->f_base);
  1060. X    free(fp->f_name);
  1061. X    fp->f_flags = 0;    /* indicates that we're available */
  1062. X}
  1063. X
  1064. int
  1065. filbuf(fp)
  1066. File    *fp;
  1067. X{
  1068. X    if (fp->f_flags & (F_EOF|F_ERR))
  1069. X        return EOF;
  1070. X    fp->f_ptr = fp->f_base;
  1071. X#ifndef MSDOS
  1072. X    do
  1073. X#endif /* MSDOS */
  1074. X        fp->f_cnt = read(fp->f_fd, fp->f_base, fp->f_bufsize);
  1075. X#ifndef MSDOS
  1076. X    while (fp->f_cnt == -1 && errno == EINTR);
  1077. X#endif /* MSDOS */
  1078. X    if (fp->f_cnt == -1) {
  1079. X        printf("[Read error %d]", errno);
  1080. X        fp->f_flags |= F_ERR;
  1081. X    }
  1082. X    if (fp->f_cnt == 0) {
  1083. X        fp->f_flags |= F_EOF;
  1084. X        return EOF;
  1085. X    }
  1086. X    io_chars += fp->f_cnt;
  1087. X    return getc(fp);
  1088. X}
  1089. X
  1090. void
  1091. putstr(s)
  1092. register char    *s;
  1093. X{
  1094. X#ifndef IBMPC
  1095. X    register int    c;
  1096. X
  1097. X    while (c = *s++)
  1098. X        putchar(c);
  1099. X#else /* IBMPC */
  1100. X    write_emif(s);
  1101. X#endif /* IBMPC */
  1102. X}
  1103. X
  1104. void
  1105. fputnchar(s, n, fp)
  1106. register char    *s;
  1107. register int    n;
  1108. register File    *fp;
  1109. X{
  1110. X    while (--n >= 0)
  1111. X        putc(*s++, fp);
  1112. X}
  1113. X
  1114. void
  1115. flusho()
  1116. X{
  1117. X#ifndef IBMPC
  1118. X    _flush(EOF, stdout);
  1119. X#endif /* IBMPC */
  1120. X}
  1121. X
  1122. void
  1123. flush(fp)
  1124. File    *fp;
  1125. X{
  1126. X    _flush(EOF, fp);
  1127. X}
  1128. X
  1129. void
  1130. f_seek(fp, offset)
  1131. register File    *fp;
  1132. off_t    offset;
  1133. X{
  1134. X    if (fp->f_flags & F_WRITE)
  1135. X        flush(fp);
  1136. X    fp->f_cnt = 0;        /* next read will filbuf(), next write
  1137. X                   will flush() with no bad effects */
  1138. X    lseek(fp->f_fd, (long) offset, L_SET);
  1139. X}
  1140. X
  1141. int        /* is void - but for lints sake */
  1142. X_flush(c, fp)
  1143. register File    *fp;
  1144. X{
  1145. X    register int    n;
  1146. X
  1147. X    if (fp->f_flags & (F_READ | F_STRING | F_ERR))
  1148. X        return EOF;
  1149. X    if (((n = (fp->f_ptr - fp->f_base)) > 0) &&
  1150. X#ifndef RAINBOW
  1151. X        (write(fp->f_fd, fp->f_base, n) != n) &&
  1152. X#else
  1153. X        (rbwrite(fp->f_fd, fp->f_base, n) != n) &&
  1154. X#endif
  1155. X        (fp != stdout)) {
  1156. X            fp->f_flags |= F_ERR;
  1157. X        error("[I/O error(%d); file = %s, fd = %d]",
  1158. X            errno, fp->f_name, fp->f_fd);
  1159. X    }
  1160. X
  1161. X    fp->f_cnt = fp->f_bufsize;
  1162. X    fp->f_ptr = fp->f_base;
  1163. X    if (c != EOF)
  1164. X        return putc(c, fp);
  1165. X}
  1166. X
  1167. int
  1168. f_gets(fp, buf, max)
  1169. register File    *fp;
  1170. char    *buf;
  1171. X{
  1172. X    register char    *cp = buf;
  1173. X    register int    c;
  1174. X    char    *endp = buf + max - 1;
  1175. X
  1176. X    if (fp->f_flags & F_EOF)
  1177. X        return EOF;
  1178. X    while (((c = getc(fp)) != EOF) && (c != '\n')) {
  1179. X        if (c == '\0')  /* possibly different from NULL */
  1180. X            break;        /* sorry we don't read nulls */
  1181. X#ifdef MSDOS
  1182. X        if (c == '\r') {
  1183. X            if ((c = getc(fp)) == '\n')
  1184. X               break;
  1185. X            else
  1186. X               *cp++ = '\r';
  1187. X        }
  1188. X#endif /* MSDOS */
  1189. X        if (cp >= endp) {
  1190. X            add_mess(" [Line too long]");
  1191. X            rbell();
  1192. X            return EOF;
  1193. X        }
  1194. X        *cp++ = c;
  1195. X    }
  1196. X    *cp = '\0';
  1197. X    if (c == EOF) {
  1198. X        if (cp != buf)
  1199. X            add_mess(" [Incomplete last line]");
  1200. X        fp->f_flags |= F_EOF;
  1201. X        return EOF;
  1202. X    }
  1203. X    io_lines += 1;
  1204. X    return 0;    /* this means okay */
  1205. X}
  1206. X
  1207. X/* skip to beginning of next line, i.e., next read returns first
  1208. X   character of new line */
  1209. X
  1210. void
  1211. f_toNL(fp)
  1212. register File    *fp;
  1213. X{
  1214. X    register int    c;
  1215. X
  1216. X    if (fp->f_flags & F_EOF)
  1217. X        return;
  1218. X    while (((c = getc(fp)) != EOF) && (c != '\n'))
  1219. X        ;
  1220. X    if (c == EOF)
  1221. X        fp->f_flags |= F_EOF;
  1222. X}
  1223. X
  1224. void
  1225. f_readn(fp, addr, n)
  1226. register File    *fp;
  1227. register char    *addr;
  1228. register int    n;
  1229. X{
  1230. X    while (--n >= 0)
  1231. X        *addr++ = getc(fp);
  1232. X}
  1233. X
  1234. int
  1235. f_getint(fp)
  1236. File    *fp;
  1237. X{
  1238. X    int    n = 0,
  1239. X        c;
  1240. X
  1241. X    while (isdigit(c = getc(fp)))
  1242. X        n = (n * 10) + c;
  1243. X    return n;
  1244. X}
  1245. X
  1246. X/* Deals with output to the terminal, setting up the amount of characters
  1247. X   to be buffered depending on the output baud rate.  Why it's in a 
  1248. X   separate file I don't know ... */
  1249. X
  1250. private char    one_buf;
  1251. X
  1252. int    BufSize = 1;
  1253. X
  1254. private File    _stdout = {1, 1, 1, F_WRITE, &one_buf, &one_buf};
  1255. File    *stdout = &_stdout;
  1256. X
  1257. X/* put a string with padding */
  1258. X
  1259. X#ifndef IBMPC
  1260. void
  1261. tputc(c)
  1262. X{
  1263. X    putchar(c);
  1264. X}
  1265. X
  1266. X#undef putchar        /* for files which forget to include io.h,
  1267. X                       here's a real putchar procedure. */
  1268. void
  1269. putchar(c)
  1270. X{
  1271. X    putc(c, stdout);
  1272. X}
  1273. X
  1274. X#endif /* IBMPC */
  1275. X#ifndef MAC
  1276. void
  1277. putpad(str, lines)
  1278. char    *str;
  1279. X{
  1280. X#ifndef IBMPC
  1281. X    if (str)
  1282. X        tputs(str, lines, tputc);
  1283. X#else /* IBMPC */
  1284. X    write_emif(str);
  1285. X#endif /* IBMPC */
  1286. X}
  1287. X#endif
  1288. X
  1289. X/* Determine the number of characters to buffer at each baud rate.  The
  1290. X   lower the number, the quicker the response when new input arrives.  Of
  1291. X   course the lower the number, the more prone the program is to stop in
  1292. X   output.  Decide what matters most to you. This sets BufSize to the right
  1293. X   number or chars, and initiaizes `stdout'.  */
  1294. X
  1295. void
  1296. settout(ttbuf)
  1297. char    *ttbuf;
  1298. X{
  1299. X#ifndef MAC
  1300. X#ifndef MSDOS
  1301. X    static int speeds[] = {
  1302. X        1,    /* 0    */
  1303. X        1,    /* 50    */
  1304. X        1,    /* 75    */
  1305. X        1,    /* 110    */
  1306. X        1,    /* 134    */
  1307. X        1,    /* 150    */
  1308. X        1,    /* 200    */
  1309. X        2,    /* 300    */
  1310. X        4,    /* 600    */
  1311. X        8,    /* 1200 */
  1312. X        16,    /* 1800    */
  1313. X        32,    /* 2400    */
  1314. X        128,    /* 4800    */
  1315. X        256,    /* 9600    */
  1316. X        512,    /* EXTA    */
  1317. X        1024    /* EXT    */
  1318. X    };
  1319. X    flusho();        /* flush the one character buffer */
  1320. X    BufSize = min(MAXTTYBUF, speeds[ospeed] * max(LI / 24, 1));
  1321. X    stdout = fd_open("/dev/tty", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
  1322. X#else /* MSDOS */
  1323. X#ifndef IBMPC
  1324. X    flusho();        /* flush the one character buffer */
  1325. X    BufSize = BUFSIZ; 
  1326. X    stdout = fd_open("con", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
  1327. X#endif    /* IBMPC */
  1328. X#endif /* MSDOS */
  1329. X#endif /* MAC */
  1330. X}
  1331. X
  1332. X#ifdef RAINBOW
  1333. X
  1334. X/*
  1335. X * use the Rainbow's video output function
  1336. X */
  1337. X
  1338. X#include <dos.h>
  1339. X
  1340. private int
  1341. rbwrite(fd, buf, cnt)
  1342. char *buf;
  1343. X{
  1344. X    union REGS vr;
  1345. X
  1346. X    if (fd != 1) {
  1347. X        write(fd, buf, cnt);
  1348. X    } else {
  1349. X        while (cnt-- > 0) {
  1350. X            vr.x.ax = *buf++;
  1351. X            vr.x.di = 0;
  1352. X            int86(0x18, &vr, &vr);
  1353. X        }
  1354. X    }
  1355. X}
  1356. X#endif /* RAINBOW */
  1357. END_OF_FILE
  1358. if test 7807 -ne `wc -c <'./fp.c'`; then
  1359.     echo shar: \"'./fp.c'\" unpacked with wrong size!
  1360. fi
  1361. # end of './fp.c'
  1362. fi
  1363. if test -f './iproc-pipes.c' -a "${1}" != "-c" ; then 
  1364.   echo shar: Will not clobber existing file \"'./iproc-pipes.c'\"
  1365. else
  1366. echo shar: Extracting \"'./iproc-pipes.c'\" \(5928 characters\)
  1367. sed "s/^X//" >'./iproc-pipes.c' <<'END_OF_FILE'
  1368. X/***************************************************************************
  1369. X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  1370. X * is provided to you without charge, and with no warranty.  You may give  *
  1371. X * away copies of JOVE, including sources, provided that this notice is    *
  1372. X * included in all the files.                                              *
  1373. X ***************************************************************************/
  1374. X
  1375. X#ifdef BSD4_2
  1376. X#   include <sys/wait.h>
  1377. X#else
  1378. X#   include <wait.h>
  1379. X#endif
  1380. X#include <signal.h>
  1381. X#include <sgtty.h>
  1382. X
  1383. X#define DEAD    1    /* Dead but haven't informed user yet */
  1384. X#define STOPPED    2    /* Job stopped */
  1385. X#define RUNNING    3    /* Just running */
  1386. X#define NEW    4    /* This process is brand new */
  1387. X
  1388. X/* If process is dead, flags says how. */
  1389. X#define EXITED    1
  1390. X#define KILLED    2
  1391. X
  1392. X#define isdead(p)    (p == 0 || proc_state(p) == DEAD || p->p_toproc == -1)
  1393. X#define makedead(p)    (proc_state(p) = DEAD)
  1394. X
  1395. X#define proc_buf(p)    (p->p_buffer->b_name)
  1396. X#define proc_cmd(p)    (p->p_name)
  1397. X#define proc_state(p)    (p->p_state)
  1398. X
  1399. private Process    *procs = 0;
  1400. X
  1401. int    ProcInput,
  1402. X    ProcOutput,
  1403. X    NumProcs = 0;
  1404. X
  1405. char *
  1406. pstate(p)
  1407. Process    *p;
  1408. X{
  1409. X    switch (proc_state(p)) {
  1410. X    case NEW:
  1411. X        return "Pre-birth";
  1412. X
  1413. X    case STOPPED:
  1414. X        return "Stopped";
  1415. X
  1416. X    case RUNNING:
  1417. X        return "Running";
  1418. X
  1419. X    case DEAD:
  1420. X        if (p->p_howdied == EXITED) {
  1421. X            if (p->p_reason == 0)
  1422. X                return "Done";
  1423. X            return sprint("Exit %d", p->p_reason);
  1424. X        }
  1425. X        return sprint("Killed %d", p->p_reason);
  1426. X
  1427. X    default:
  1428. X        return "Unknown state";
  1429. X    }
  1430. X}
  1431. X
  1432. static Process *
  1433. proc_pid(pid)
  1434. X{
  1435. X    register Process    *p;
  1436. X
  1437. X    for (p = procs; p != 0; p = p->p_next)
  1438. X        if (p->p_portpid == pid)
  1439. X            break;
  1440. X
  1441. X    return p;
  1442. X}
  1443. X
  1444. procs_read()
  1445. X{
  1446. X    struct header {
  1447. X        int    pid;
  1448. X        int    nbytes;
  1449. X    } header;
  1450. X    int    n;
  1451. X    long    nbytes;
  1452. X    static int    here = NO;
  1453. X
  1454. X    if (here)    
  1455. X        return;
  1456. X    sighold(SIGCHLD);    /* block any other children */
  1457. X    here = YES;
  1458. X    for (;;) {
  1459. X        (void) ioctl(ProcInput, FIONREAD, (struct sgttyb *) &nbytes);
  1460. X        if (nbytes < sizeof header)
  1461. X            break;
  1462. X        n = read(ProcInput, (char *) &header, sizeof header);
  1463. X        if (n != sizeof header)
  1464. X            finish(1);
  1465. X        read_proc(header.pid, header.nbytes);
  1466. X    }
  1467. X    here = NO;
  1468. X    sigrelse(SIGCHLD);
  1469. X}
  1470. X
  1471. read_proc(pid, nbytes)
  1472. int    pid;
  1473. register int    nbytes;
  1474. X{
  1475. X    register Process    *p;
  1476. X    int    n;
  1477. X    char    ibuf[512];
  1478. X
  1479. X    if ((p = proc_pid(pid)) == 0) {
  1480. X        printf("\riproc: unknown pid (%d)", pid);
  1481. X        return;
  1482. X    }
  1483. X    if (proc_state(p) == NEW) {
  1484. X        int    rpid;
  1485. X        /* pid of real child, not of portsrv */
  1486. X
  1487. X        doread(ProcInput, (char *) &rpid, nbytes);
  1488. X        nbytes -= sizeof rpid;
  1489. X        p->p_pid = rpid;
  1490. X        p->p_state = RUNNING;
  1491. X    }
  1492. X
  1493. X    if (nbytes == EOF) {        /* okay to clean up this process */
  1494. X        proc_close(p);
  1495. X        makedead(p);
  1496. X        return;
  1497. X    }
  1498. X
  1499. X    while (nbytes > 0) {
  1500. X        n = min((sizeof ibuf) - 1, nbytes);
  1501. X        doread(ProcInput, ibuf, n);
  1502. X        ibuf[n] = 0;    /* Null terminate for convenience */
  1503. X        nbytes -= n;
  1504. X        proc_rec(p, ibuf);
  1505. X    }
  1506. X}
  1507. X
  1508. ProcKill()
  1509. X{
  1510. X    proc_kill(curbuf->b_process, SIGKILL);
  1511. X}
  1512. X
  1513. ProcInt()
  1514. X{
  1515. X    proc_kill(curbuf->b_process, SIGINT);
  1516. X}
  1517. X
  1518. ProcQuit()
  1519. X{
  1520. X    proc_kill(curbuf->b_process, SIGQUIT);
  1521. X}
  1522. X
  1523. private
  1524. proc_close(p)
  1525. Process    *p;
  1526. X{
  1527. X    sighold(SIGCHLD);
  1528. X
  1529. X    if (p->p_toproc >= 0) {
  1530. X        (void) close(p->p_toproc);
  1531. X        p->p_toproc = -1;    /* writes will fail */
  1532. X        NumProcs -= 1;
  1533. X    }
  1534. X
  1535. X    sigrelse(SIGCHLD);
  1536. X}
  1537. X
  1538. do_rtp(mp)
  1539. register Mark    *mp;
  1540. X{
  1541. X    register Process    *p = curbuf->b_process;
  1542. X    Line    *line1 = curline,
  1543. X        *line2 = mp->m_line;
  1544. X    int    char1 = curchar,
  1545. X        char2 = mp->m_char;
  1546. X    char    *gp;
  1547. X
  1548. X    if (isdead(p) || p->p_buffer != curbuf)
  1549. X        return;
  1550. X
  1551. X    (void) fixorder(&line1, &char1, &line2, &char2);
  1552. X    while (line1 != line2->l_next) {
  1553. X        gp = ltobuf(line1, genbuf) + char1;
  1554. X        if (line1 == line2)
  1555. X            gp[char2] = '\0';
  1556. X        else
  1557. X            strcat(gp, "\n");
  1558. X        (void) write(p->p_toproc, gp, strlen(gp));
  1559. X        line1 = line1->l_next;
  1560. X        char1 = 0;
  1561. X    }
  1562. X}
  1563. X
  1564. X/* VARARGS3 */
  1565. X
  1566. private
  1567. proc_strt(bufname, clobber, va_alist)
  1568. char    *bufname;
  1569. va_dcl
  1570. X{
  1571. X    Window    *owind = curwind;
  1572. X    int    toproc[2],
  1573. X        pid;
  1574. X    Process    *newp;
  1575. X    Buffer    *newbuf;
  1576. X        char    *argv[32],
  1577. X            *cp,
  1578. X            foo[10],
  1579. X        cmdbuf[128];
  1580. X        int    i;
  1581. X    va_list    ap;
  1582. X
  1583. X    isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  1584. X                   or is of type B_PROCESS */
  1585. X    dopipe(toproc);
  1586. X
  1587. X    sighold(SIGCHLD);
  1588. X#ifdef SIGWINCH
  1589. X    sighold(SIGWINCH);
  1590. X#endif
  1591. X    switch (pid = fork()) {
  1592. X    case -1:
  1593. X        pclose(toproc);
  1594. X        complain("[Fork failed.]");
  1595. X
  1596. X    case 0:
  1597. X        sigrelse(SIGCHLD);
  1598. X#ifdef SIGWINCH
  1599. X        sigrelse(SIGWINCH);
  1600. X#endif
  1601. X            argv[0] = "portsrv";
  1602. X            argv[1] = foo;
  1603. X        sprintf(foo, "%d", ProcInput);
  1604. X        va_start(ap);
  1605. X        make_argv(&argv[2], ap);
  1606. X        va_end(ap);
  1607. X        (void) dup2(toproc[0], 0);
  1608. X        (void) dup2(ProcOutput, 1);
  1609. X        (void) dup2(ProcOutput, 2);
  1610. X        pclose(toproc);
  1611. X        execv(Portsrv, argv);
  1612. X        printf("execl failed\n");
  1613. X        _exit(1);
  1614. X    }
  1615. X
  1616. X    newp = (Process *) malloc(sizeof *newp);
  1617. X    newp->p_next = procs;
  1618. X    newp->p_state = NEW;
  1619. X    newp->p_cmd = 0;
  1620. X
  1621. X    cmdbuf[0] = '\0';
  1622. X    va_start(ap);
  1623. X    while (cp = va_arg(ap, char *))
  1624. X        sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp);
  1625. X    va_end(ap);
  1626. X    newp->p_name = copystr(cmdbuf);
  1627. X    procs = newp;
  1628. X    newp->p_portpid = pid;
  1629. X    newp->p_pid = -1;
  1630. X
  1631. X    newbuf = do_select((Window *) 0, bufname);
  1632. X    newbuf->b_type = B_PROCESS;
  1633. X    newp->p_buffer = newbuf;
  1634. X    newbuf->b_process = newp;    /* sorta circular, eh? */
  1635. X    pop_wind(bufname, clobber, B_PROCESS);
  1636. X    ToLast();
  1637. X    if (!bolp())
  1638. X        LineInsert(1);
  1639. X    /* Pop_wind() after everything is set up; important!
  1640. X       Bindings won't work right unless newbuf->b_process is already
  1641. X       set up BEFORE NEWBUF is first SetBuf()'d. */
  1642. X    newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
  1643. X
  1644. X    newp->p_toproc = toproc[1];
  1645. X    newp->p_reason = 0;
  1646. X    NumProcs += 1;
  1647. X    (void) close(toproc[0]);
  1648. X    SetWind(owind);
  1649. X    sigrelse(SIGCHLD);
  1650. X#ifdef SIGWINCH
  1651. X    sigrelse(SIGWINCH);
  1652. X#endif
  1653. X}
  1654. X
  1655. pinit()
  1656. X{
  1657. X    int    p[2];
  1658. X
  1659. X    (void) signal(SIGCHLD, proc_child);
  1660. X    (void) pipe(p);
  1661. X    ProcInput = p[0];
  1662. X    ProcOutput = p[1];
  1663. X    (void) signal(INPUT_SIG, procs_read);
  1664. X    sighold(INPUT_SIG);    /* Released during terminal read */
  1665. X}
  1666. X
  1667. doread(fd, buf, n)
  1668. char    *buf;
  1669. X{
  1670. X    int    nread;
  1671. X
  1672. X    if ((nread = read(fd, buf, n)) != n)
  1673. X        complain("Cannot read %d (got %d) bytes.", n, nread);
  1674. X}
  1675. END_OF_FILE
  1676. if test 5928 -ne `wc -c <'./iproc-pipes.c'`; then
  1677.     echo shar: \"'./iproc-pipes.c'\" unpacked with wrong size!
  1678. fi
  1679. # end of './iproc-pipes.c'
  1680. fi
  1681. if test -f './iproc-ptys.c' -a "${1}" != "-c" ; then 
  1682.   echo shar: Will not clobber existing file \"'./iproc-ptys.c'\"
  1683. else
  1684. echo shar: Extracting \"'./iproc-ptys.c'\" \(7915 characters\)
  1685. sed "s/^X//" >'./iproc-ptys.c' <<'END_OF_FILE'
  1686. X/***************************************************************************
  1687. X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  1688. X * is provided to you without charge, and with no warranty.  You may give  *
  1689. X * away copies of JOVE, including sources, provided that this notice is    *
  1690. X * included in all the files.                                              *
  1691. X ***************************************************************************/
  1692. X
  1693. X#ifdef BSD4_2
  1694. X#   include <sys/wait.h>
  1695. X#else
  1696. X#   include <wait.h>
  1697. X#endif
  1698. X#include <signal.h>
  1699. X#include <sgtty.h>
  1700. X#include <errno.h>
  1701. X
  1702. X#define DEAD    1    /* dead but haven't informed user yet */
  1703. X#define STOPPED    2    /* job stopped */
  1704. X#define RUNNING    3    /* just running */
  1705. X#define NEW    4    /* brand new, never been ... received no input */
  1706. X
  1707. X/* If process is dead, flags says how. */
  1708. X#define EXITED    1
  1709. X#define KILLED    2
  1710. X
  1711. X#define isdead(p)    (p == 0 || proc_state(p) == DEAD || p->p_fd == -1)
  1712. X#define makedead(p)    (proc_state(p) = DEAD)
  1713. X
  1714. X#define proc_buf(p)    (p->p_buffer->b_name)
  1715. X#define proc_cmd(p)    (p->p_name)
  1716. X#define proc_state(p)    (p->p_state)
  1717. X
  1718. private Process    *procs = 0;
  1719. X
  1720. long    global_fd = 1;
  1721. int    NumProcs = 0;
  1722. X
  1723. X#ifdef BRLUNIX
  1724. X    extern struct sg_brl sg1;
  1725. X#else
  1726. X    extern struct sgttyb sg1;
  1727. X#endif
  1728. X
  1729. extern struct tchars tc1;
  1730. X
  1731. X#ifdef TIOCSLTC
  1732. X    extern struct ltchars ls1;
  1733. X#endif
  1734. X
  1735. char *
  1736. pstate(p)
  1737. Process    *p;
  1738. X{
  1739. X    switch (proc_state(p)) {
  1740. X    case STOPPED:
  1741. X        return "Stopped";
  1742. X
  1743. X    case RUNNING:
  1744. X        return "Running";
  1745. X
  1746. X    case DEAD:
  1747. X        if (p->p_howdied == EXITED) {
  1748. X            if (p->p_reason == 0)
  1749. X                return "Done";
  1750. X            return sprint("Exit %d", p->p_reason);
  1751. X        }
  1752. X        return sprint("Killed %d", p->p_reason);
  1753. X
  1754. X    case NEW:
  1755. X        return "New";
  1756. X
  1757. X    default:
  1758. X        return "Unknown state";
  1759. X    }
  1760. X}
  1761. X
  1762. static Process *
  1763. proc_pid(pid)
  1764. X{
  1765. X    register Process    *p;
  1766. X
  1767. X    for (p = procs; p != 0; p = p->p_next)
  1768. X        if (p->p_pid == pid)
  1769. X            break;
  1770. X
  1771. X    return p;
  1772. X}
  1773. X
  1774. read_proc(fd)
  1775. register int    fd;
  1776. X{
  1777. X    register Process    *p;
  1778. X    unsigned int    n;
  1779. X    char    ibuf[1024];
  1780. X
  1781. X    for (p = procs; p != 0; p = p->p_next)
  1782. X        if (p->p_fd == fd)
  1783. X            break;
  1784. X
  1785. X    if (p == 0) {
  1786. X        printf("\riproc: unknown fd %d", fd);
  1787. X        return;
  1788. X    }
  1789. X
  1790. X    n = read(fd, ibuf, sizeof(ibuf) - 1);
  1791. X    if (n == -1 && errno == EIO) {
  1792. X        if (proc_state(p) == NEW)
  1793. X            return;
  1794. X        proc_close(p);
  1795. X        makedead(p);
  1796. X        return;
  1797. X    } else {
  1798. X        if (proc_state(p) != RUNNING) {
  1799. X            proc_state(p) = RUNNING;
  1800. X            UpdModLine = YES;
  1801. X        }
  1802. X    }
  1803. X    if (n <= 0) {
  1804. X        if (n == 0)
  1805. X            strcpy(ibuf, "[Process EOF]");
  1806. X        else
  1807. X            sprintf(ibuf, "\n[pty read error: %d]\n", errno);
  1808. X    } else
  1809. X        ibuf[n] = '\0';
  1810. X    proc_rec(p, ibuf);
  1811. X}
  1812. X
  1813. ProcKill()
  1814. X{
  1815. X    register Buffer    *b;
  1816. X    Process    *buf_to_proc();
  1817. X    char    *bname;
  1818. X
  1819. X    bname = ask_buf(curbuf);
  1820. X
  1821. X    if ((b = buf_exists(bname)) == 0)
  1822. X        complain("[No such buffer]");
  1823. X    if (b->b_process == 0)
  1824. X        complain("%s not tied to a process.", bname);
  1825. X    proc_kill(b->b_process, SIGKILL);
  1826. X}
  1827. X
  1828. ProcCont()
  1829. X{
  1830. X    Process    *p;
  1831. X
  1832. X    if ((p = curbuf->b_process) == 0)
  1833. X        complain("[No process]");
  1834. X    if (p->p_state != DEAD) {
  1835. X        proc_kill(p, SIGCONT);
  1836. X        p->p_state = RUNNING;
  1837. X    }        
  1838. X}
  1839. X
  1840. ProcEof()
  1841. X{
  1842. X    send_p(tc1.t_eofc);
  1843. X}
  1844. X
  1845. ProcInt()
  1846. X{
  1847. X    send_p(tc1.t_intrc);
  1848. X}
  1849. X
  1850. ProcQuit()
  1851. X{
  1852. X    send_p(tc1.t_quitc);
  1853. X}
  1854. X
  1855. ProcStop()
  1856. X{
  1857. X    send_p(ls1.t_suspc);
  1858. X}
  1859. X
  1860. ProcDStop()
  1861. X{
  1862. X    send_p(ls1.t_dsuspc);
  1863. X}
  1864. X
  1865. send_p(c)
  1866. char    c;
  1867. X{
  1868. X    Process    *p;
  1869. X    char    buf[2];
  1870. X
  1871. X    if ((p = curbuf->b_process) == 0)
  1872. X        complain("[No process]");
  1873. X    ToLast();
  1874. X    buf[0] = c;
  1875. X    buf[1] = '\0';
  1876. X    proc_rec(p, buf);
  1877. X    (void) write(p->p_fd, &c, 1);
  1878. X}
  1879. X
  1880. private
  1881. proc_close(p)
  1882. Process *p;
  1883. X{
  1884. X    sighold(SIGCHLD);    /* be mutually exclusive */
  1885. X
  1886. X    if (p->p_fd >= 0) {
  1887. X        (void) close(p->p_fd);
  1888. X        global_fd &= ~(1L << p->p_fd);
  1889. X        NumProcs -= 1;
  1890. X        p->p_fd = -1;
  1891. X    }
  1892. X
  1893. X    sigrelse(SIGCHLD);
  1894. X}
  1895. X
  1896. do_rtp(mp)
  1897. register Mark    *mp;
  1898. X{
  1899. X    register Process    *p = curbuf->b_process;
  1900. X    Line    *line1 = curline,
  1901. X        *line2 = mp->m_line;
  1902. X    int    char1 = curchar,
  1903. X        char2 = mp->m_char;
  1904. X    char    *gp;
  1905. X    int    nbytes;
  1906. X
  1907. X    if (isdead(p) || p->p_buffer != curbuf)
  1908. X        return;
  1909. X
  1910. X    (void) fixorder(&line1, &char1, &line2, &char2);
  1911. X    while (line1 != line2->l_next) {
  1912. X        gp = ltobuf(line1, genbuf) + char1;
  1913. X        if (line1 == line2)
  1914. X            gp[char2] = '\0';
  1915. X        else
  1916. X            strcat(gp, "\n");
  1917. X        if (nbytes = strlen(gp))
  1918. X            (void) write(p->p_fd, gp, nbytes);
  1919. X        line1 = line1->l_next;
  1920. X        char1 = 0;
  1921. X    }
  1922. X}
  1923. X
  1924. X/* VARARGS2 */
  1925. X
  1926. private
  1927. proc_strt(bufname, clobber, va_alist)
  1928. char    *bufname;
  1929. va_dcl
  1930. X{
  1931. X    va_list    ap;
  1932. X    char    *argv[32],
  1933. X        *cp;
  1934. X    Window *owind = curwind;
  1935. X    int    pid;
  1936. X    Process    *newp;
  1937. X    Buffer     *newbuf;
  1938. X    int    i,
  1939. X        ptyfd,
  1940. X        ttyfd,
  1941. X         ldisc,
  1942. X        lmode;
  1943. X    register char    *s,
  1944. X            *t;
  1945. X    extern int    errno;
  1946. X    static char    ttybuf[11],
  1947. X            ptybuf[11];
  1948. X    char    cmdbuf[128];
  1949. X#ifdef BRLUNIX
  1950. X    struct sg_brl sg;
  1951. X#else
  1952. X    struct sgttyb sg;
  1953. X#endif
  1954. X
  1955. X#ifdef TIOCGWINSZ
  1956. X    struct winsize win;
  1957. X#else
  1958. X#  ifdef BTL_BLIT
  1959. X#  include <sys/jioctl.h>
  1960. X    struct jwinsize jwin;
  1961. X#  endif
  1962. X#endif
  1963. X
  1964. X    isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  1965. X                   or is of type B_PROCESS */
  1966. X    for (s = "pqrs"; *s; s++) {
  1967. X        for (t = "0123456789abcdef"; *t; t++) {
  1968. X            sprintf(ptybuf, "/dev/pty%c%c", *s, *t);
  1969. X            if ((ptyfd = open(ptybuf, 2)) >= 0) {
  1970. X                strcpy(ttybuf, ptybuf);
  1971. X                ttybuf[5] = 't';
  1972. X                /* make sure both ends are available */
  1973. X                if ((i = open(ttybuf, 2)) < 0)
  1974. X                    continue;
  1975. X                (void) close(i);
  1976. X                goto out;
  1977. X            }
  1978. X        }
  1979. X    }
  1980. X
  1981. out:    if (s == 0 && t == 0)
  1982. X        complain("[Out of ptys!]");
  1983. X
  1984. X#ifdef TIOCGETD
  1985. X    (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc);
  1986. X#endif
  1987. X#ifdef TIOCLGET
  1988. X    (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode);
  1989. X#endif
  1990. X#ifdef TIOCGWINSZ
  1991. X    (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win);
  1992. X#else
  1993. X#  ifdef BTL_BLIT
  1994. X    (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin);
  1995. X#  endif /* BTL_BLIT */
  1996. X#endif
  1997. X
  1998. X    sighold(SIGCHLD);
  1999. X#ifdef SIGWINCH
  2000. X    sighold(SIGWINCH);
  2001. X#endif
  2002. X    switch (pid = fork()) {
  2003. X    case -1:
  2004. X        (void) close(ptyfd);
  2005. X        message("[Fork failed!]");
  2006. X        goto fail;
  2007. X
  2008. X    case 0:
  2009. X        sigrelse(SIGCHLD);
  2010. X#ifdef SIGWINCH
  2011. X        sigrelse(SIGWINCH);
  2012. X#endif
  2013. X        for (i = 0; i < 32; i++)
  2014. X            (void) close(i);
  2015. X
  2016. X#ifdef TIOCNOTTY
  2017. X        if ((i = open("/dev/tty", 2)) >= 0) {
  2018. X            (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0);
  2019. X            (void) close(i);
  2020. X        }
  2021. X#endif
  2022. X        if ((ttyfd = open(ttybuf, 2)) < 0)
  2023. X            exit(-1);
  2024. X        (void) dup2(ttyfd, 1);
  2025. X        (void) dup2(ttyfd, 2);
  2026. X
  2027. X#ifdef TIOCSETD
  2028. X        (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc);
  2029. X#endif
  2030. X#ifdef TIOCLSET
  2031. X        (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode);
  2032. X#endif
  2033. X#ifdef TIOCSETC
  2034. X        (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1);
  2035. X#endif
  2036. X#ifdef TIOCSLTC
  2037. X        (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1);
  2038. X#endif
  2039. X
  2040. X#ifdef TIOCGWINSZ
  2041. X#    ifdef SIGWINCH
  2042. X        (void) signal(SIGWINCH, SIG_IGN);
  2043. X#    endif
  2044. X        win.ws_row = curwind->w_height;
  2045. X        (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win);
  2046. X#else
  2047. X#  ifdef BTL_BLIT
  2048. X        jwin.bytesy = curwind->w_height;
  2049. X        (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin);
  2050. X#  endif
  2051. X#endif
  2052. X
  2053. X        sg = sg1;
  2054. X        sg.sg_flags &= ~(ECHO | CRMOD);
  2055. X        (void) stty(0, &sg);
  2056. X
  2057. X        i = getpid();
  2058. X        (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i);
  2059. X        (void) setpgrp(0, i);
  2060. X        va_start(ap);
  2061. X        make_argv(argv, ap);
  2062. X        va_end(ap);
  2063. X        execv(argv[0], &argv[1]);
  2064. X        (void) write(1, "execve failed!\n", 15);
  2065. X        _exit(errno + 1);
  2066. X    }
  2067. X
  2068. X    newp = (Process *) emalloc(sizeof *newp);
  2069. X
  2070. X    newp->p_fd = ptyfd;
  2071. X    newp->p_pid = pid;
  2072. X
  2073. X    newbuf = do_select((Window *) 0, bufname);
  2074. X    newbuf->b_type = B_PROCESS;
  2075. X    newp->p_buffer = newbuf;
  2076. X    newbuf->b_process = newp;    /* sorta circular, eh? */
  2077. X    pop_wind(bufname, clobber, B_PROCESS);
  2078. X    /* Pop_wind() after everything is set up; important!
  2079. X       Bindings won't work right unless newbuf->b_process is already
  2080. X       set up BEFORE NEWBUF is first SetBuf()'d. */
  2081. X    ToLast();
  2082. X    if (!bolp())
  2083. X        LineInsert(1);
  2084. X
  2085. X    cmdbuf[0] = '\0';
  2086. X    va_start(ap);
  2087. X    while (cp = va_arg(ap, char *))
  2088. X        sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp++);
  2089. X    va_end(ap);
  2090. X
  2091. X    newp->p_name = copystr(cmdbuf);
  2092. X    newp->p_state = NEW;
  2093. X    newp->p_reason = 0;
  2094. X    newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
  2095. X
  2096. X    newp->p_next = procs;
  2097. X    procs = newp;
  2098. X    NumProcs += 1;
  2099. X    global_fd |= 1L << newp->p_fd;
  2100. X    SetWind(owind);
  2101. X
  2102. fail:    sigrelse(SIGCHLD);
  2103. X#ifdef SIGWINCH
  2104. X    sigrelse(SIGWINCH);
  2105. X#endif
  2106. X}
  2107. X    
  2108. pinit()
  2109. X{
  2110. X    (void) signal(SIGCHLD, proc_child);
  2111. X}
  2112. X
  2113. END_OF_FILE
  2114. if test 7915 -ne `wc -c <'./iproc-ptys.c'`; then
  2115.     echo shar: \"'./iproc-ptys.c'\" unpacked with wrong size!
  2116. fi
  2117. # end of './iproc-ptys.c'
  2118. fi
  2119. if test -f './macros.c' -a "${1}" != "-c" ; then 
  2120.   echo shar: Will not clobber existing file \"'./macros.c'\"
  2121. else
  2122. echo shar: Extracting \"'./macros.c'\" \(7870 characters\)
  2123. sed "s/^X//" >'./macros.c' <<'END_OF_FILE'
  2124. X/***************************************************************************
  2125. X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  2126. X * is provided to you without charge, and with no warranty.  You may give  *
  2127. X * away copies of JOVE, including sources, provided that this notice is    *
  2128. X * included in all the files.                                              *
  2129. X ***************************************************************************/
  2130. X
  2131. X#include "jove.h"
  2132. X#include "ctype.h"
  2133. X#include "io.h"
  2134. X
  2135. X#ifdef MAC
  2136. X#    undef private
  2137. X#    define private
  2138. X#endif
  2139. X
  2140. X#ifdef    LINT_ARGS
  2141. private void
  2142. X    add_mac(struct macro *),
  2143. X    del_mac(struct macro *),
  2144. X    pop_macro_stack(void),
  2145. X    push_macro_stack(struct macro *, int);
  2146. X    
  2147. private int
  2148. X    PrefChar(int);
  2149. X
  2150. private struct macro * mac_exists(char *);
  2151. X#else
  2152. private void
  2153. X    add_mac(),
  2154. X    del_mac(),
  2155. X    pop_macro_stack(),
  2156. X    push_macro_stack();
  2157. X    
  2158. private int
  2159. X    PrefChar();
  2160. X
  2161. private struct macro * mac_exists();
  2162. X#endif    /* LINT_ARGS */
  2163. X
  2164. X#ifdef MAC
  2165. X#    undef private
  2166. X#    define private static
  2167. X#endif
  2168. X
  2169. struct macro    *macros = 0;        /* macros */
  2170. int    InMacDefine = NO;
  2171. X
  2172. private void
  2173. add_mac(new)
  2174. struct macro    *new;
  2175. X{
  2176. X    register struct macro    *mp,
  2177. X                *prev = 0;
  2178. X
  2179. X    for (mp = macros; mp != 0; prev = mp, mp = mp->m_nextm)
  2180. X        if (mp == new)
  2181. X            return;
  2182. X
  2183. X    if (prev)
  2184. X        prev->m_nextm = new;
  2185. X    else
  2186. X        macros = new;
  2187. X    new->m_nextm = 0;
  2188. X    new->Type = MACRO;
  2189. X}
  2190. X
  2191. private void
  2192. del_mac(mac)
  2193. struct macro    *mac;
  2194. X{
  2195. X    register struct macro    *m;
  2196. X
  2197. X    for (m = macros; m != 0; m = m->m_nextm)
  2198. X        if (m->m_nextm == mac) {
  2199. X            m->m_nextm = mac->m_nextm;
  2200. X            break;
  2201. X        }
  2202. X    free(mac->Name);
  2203. X    free(mac->m_body);
  2204. X    free((char *) mac);
  2205. X}
  2206. X
  2207. struct macro    KeyMacro;    /* Macro used for defining */
  2208. X
  2209. X/* To execute a macro, we have a "stack" of running macros.  Whenever
  2210. X   we execute a macro, we push it on the stack, run it, then pop it
  2211. X   from the stack.  */
  2212. struct m_thread {
  2213. X    struct m_thread    *mt_prev;
  2214. X    struct macro    *mt_mp;
  2215. X    int    mt_offset,
  2216. X        mt_count;
  2217. X};
  2218. X
  2219. private struct m_thread    *mac_stack = 0;
  2220. X
  2221. void
  2222. unwind_macro_stack()
  2223. X{
  2224. X    while (mac_stack != 0)
  2225. X        pop_macro_stack();
  2226. X}
  2227. X
  2228. private void
  2229. pop_macro_stack()
  2230. X{
  2231. X    register struct m_thread    *m;
  2232. X
  2233. X    if ((m = mac_stack) == 0)
  2234. X        return;
  2235. X    mac_stack = m->mt_prev;
  2236. X    free_mthread(m);
  2237. X}
  2238. X
  2239. struct m_thread *
  2240. alloc_mthread()
  2241. X{
  2242. X    return (struct m_thread *) emalloc(sizeof (struct m_thread));
  2243. X}
  2244. X
  2245. void
  2246. free_mthread(t)
  2247. struct m_thread    *t;
  2248. X{
  2249. X    free((char *) t);
  2250. X}
  2251. X
  2252. private void
  2253. push_macro_stack(m, count)
  2254. struct macro    *m;
  2255. X{
  2256. X    struct m_thread    *t;
  2257. X
  2258. X    t = alloc_mthread();
  2259. X    t->mt_prev = mac_stack;
  2260. X    mac_stack = t;
  2261. X    t->mt_offset = 0;
  2262. X    t->mt_mp = m;
  2263. X    t->mt_count = count;
  2264. X}
  2265. X
  2266. void
  2267. do_macro(mac)
  2268. struct macro    *mac;
  2269. X{
  2270. X    push_macro_stack(mac, arg_value());
  2271. X}
  2272. X
  2273. private struct macro *
  2274. mac_exists(name)
  2275. char    *name;
  2276. X{
  2277. X    register struct macro    *mp;
  2278. X
  2279. X    for (mp = macros; mp; mp = mp->m_nextm)
  2280. X        if (strcmp(mp->Name, name) == 0)
  2281. X            return mp;
  2282. X    return 0;
  2283. X}
  2284. X
  2285. void
  2286. mac_init()
  2287. X{
  2288. X    add_mac(&KeyMacro);
  2289. X    KeyMacro.Name = "keyboard-macro";
  2290. X    KeyMacro.m_len = 0;
  2291. X    KeyMacro.m_buflen = 16;
  2292. X    KeyMacro.m_body = emalloc(KeyMacro.m_buflen);
  2293. X}
  2294. X
  2295. void
  2296. mac_putc(c)
  2297. int    c;
  2298. X{
  2299. X    if (KeyMacro.m_len >= KeyMacro.m_buflen) {
  2300. X        KeyMacro.m_buflen += 16;
  2301. X        KeyMacro.m_body = realloc(KeyMacro.m_body, (unsigned) KeyMacro.m_buflen);
  2302. X        if (KeyMacro.m_body == 0) {
  2303. X            KeyMacro.m_buflen = KeyMacro.m_len = 0;
  2304. X            complain("[Can't allocate storage for keyboard macro]");
  2305. X        }
  2306. X    }
  2307. X    KeyMacro.m_body[KeyMacro.m_len++] = c;
  2308. X}
  2309. X
  2310. int
  2311. in_macro()
  2312. X{
  2313. X    return (mac_stack != 0);
  2314. X}
  2315. X
  2316. int
  2317. mac_getc()
  2318. X{
  2319. X    struct m_thread    *mthread;
  2320. X    struct macro    *m;
  2321. X
  2322. X    if ((mthread = mac_stack) == 0)
  2323. X        return -1;
  2324. X    m = mthread->mt_mp;
  2325. X    if (mthread->mt_offset == m->m_len) {
  2326. X        mthread->mt_offset = 0;
  2327. X        if (--mthread->mt_count == 0)
  2328. X            pop_macro_stack();
  2329. X        return mac_getc();
  2330. X    }
  2331. X    return m->m_body[mthread->mt_offset++];
  2332. X}
  2333. X
  2334. void
  2335. NameMac()
  2336. X{
  2337. X    char    *name;
  2338. X    struct macro    *m;
  2339. X
  2340. X    if (KeyMacro.m_len == 0)
  2341. X        complain("[No keyboard macro to name!]");
  2342. X    if (in_macro() || InMacDefine)
  2343. X        complain("[Can't name while defining/executing]");
  2344. X    if ((m = mac_exists(name = ask((char *) 0, ProcFmt))) == 0)
  2345. X        m = (struct macro *) emalloc(sizeof *m);
  2346. X    else {
  2347. X        if (strcmp(name, KeyMacro.Name) == 0)
  2348. X            complain("[Can't name it that!]");
  2349. X        free(m->Name);
  2350. X        free(m->m_body);
  2351. X    }
  2352. X    name = copystr(name);
  2353. X    m->Type = KeyMacro.Type;
  2354. X    m->m_len = KeyMacro.m_len;
  2355. X    m->m_buflen = KeyMacro.m_buflen;
  2356. X    m->m_body = emalloc(m->m_buflen);
  2357. X    byte_copy(KeyMacro.m_body, m->m_body, m->m_len);
  2358. X    m->m_flags = SAVE;
  2359. X    m->Name = name;
  2360. X    add_mac(m);
  2361. X}
  2362. X
  2363. void
  2364. RunMacro()
  2365. X{
  2366. X    struct macro    *m;
  2367. X
  2368. X    if (m = (struct macro *) findmac(ProcFmt))
  2369. X        do_macro(m);
  2370. X}
  2371. X
  2372. void
  2373. pr_putc(c, fp)
  2374. File    *fp;
  2375. X{
  2376. X    if (c == '\\' || c == '^')
  2377. X        putc('\\', fp);
  2378. X     else if (isctrl(c)) {
  2379. X        putc('^', fp);
  2380. X        c = (c == RUBOUT) ? '?' : (c + '@');
  2381. X    }
  2382. X    putc(c, fp);
  2383. X}
  2384. X
  2385. void
  2386. WriteMacs()
  2387. X{
  2388. X    struct macro    *m;
  2389. X    char    *file,
  2390. X        filebuf[FILESIZE];
  2391. X    File    *fp;
  2392. X    int    i;
  2393. X
  2394. X    file = ask_file((char *) 0, (char *) 0, filebuf);
  2395. X    fp = open_file(file, iobuff, F_WRITE, COMPLAIN, QUIET);
  2396. X
  2397. X    /* Don't write the keyboard macro which is always the first */
  2398. X    for (m = macros->m_nextm; m != 0; m = m->m_nextm) {
  2399. X        fprintf(fp, "define-macro %s ", m->Name);
  2400. X        for (i = 0; i < m->m_len; i++)
  2401. X            pr_putc(m->m_body[i], fp);
  2402. X        putc('\n', fp);
  2403. X        m->m_flags &= ~SAVE;
  2404. X    }
  2405. X    close_file(fp);
  2406. X}
  2407. X
  2408. void
  2409. DefKBDMac()
  2410. X{
  2411. X    char    *macro_name,
  2412. X        *macro_body,
  2413. X        nextc,
  2414. X        c,
  2415. X        macro_buffer[LBSIZE];
  2416. X    int    i;
  2417. X    struct macro    *m;
  2418. X
  2419. X    macro_name = do_ask(" \r\n", (int (*)()) 0, (char *) 0, ProcFmt);
  2420. X    if (macro_name == 0)
  2421. X        complain("[No default]");
  2422. X    macro_name = copystr(macro_name);
  2423. X    if (m = mac_exists(macro_name))
  2424. X        del_mac(m);
  2425. X    macro_body = ask((char *) 0, ": %f %s enter body: ", macro_name);
  2426. X    i = 0;
  2427. X    while ((c = *macro_body++) != '\0') {
  2428. X        if (c == '\\') {
  2429. X            if ((nextc = *macro_body++) == LF)
  2430. X                complain("[Premature end of line]");
  2431. X            c = nextc;
  2432. X        } else if (c == '^') {
  2433. X            if ((nextc = *macro_body++) == '?')
  2434. X                c = RUBOUT;
  2435. X            else if (isalpha(nextc) || index("@[\\]^_", nextc))
  2436. X                c = CTL(nextc);
  2437. X            else
  2438. X                complain("Bad control-character: '%c'", nextc);
  2439. X        }
  2440. X        macro_buffer[i++] = c;
  2441. X    }
  2442. X    m = (struct macro *) emalloc(sizeof (*m));
  2443. X    m->Name = macro_name;
  2444. X    m->m_len = m->m_buflen = i;
  2445. X    m->m_body = emalloc(i);
  2446. X    m->m_flags = InJoverc ? 0 : SAVE;
  2447. X    byte_copy(macro_buffer, m->m_body, i);
  2448. X    add_mac(m);
  2449. X}
  2450. X
  2451. void
  2452. Remember()
  2453. X{
  2454. X    /* We're already executing the macro; ignore any attempts
  2455. X       to define the keyboard macro while we are executing. */
  2456. X    if (in_macro())
  2457. X        return;
  2458. X    if (InMacDefine)
  2459. X        message("[Already defining ... continue with definition]");
  2460. X    else {
  2461. X        UpdModLine = YES;
  2462. X        InMacDefine = YES;
  2463. X        KeyMacro.m_len = 0;
  2464. X        message("Defining...");
  2465. X    }
  2466. X}
  2467. X
  2468. X/* Is `c' a prefix character */
  2469. X
  2470. private int
  2471. PrefChar(c)
  2472. X{
  2473. X    return (int) IsPrefix(mainmap[c]);
  2474. X}
  2475. X
  2476. void
  2477. Forget()
  2478. X{
  2479. X    char    *cp;
  2480. X    struct macro    *m = &KeyMacro;
  2481. X
  2482. X    UpdModLine = YES;
  2483. X    if (InMacDefine) {
  2484. X        message("Keyboard macro defined.");
  2485. X        InMacDefine = NO;
  2486. X
  2487. X        /* try and strip off the key sequence that invoked us */
  2488. X        cp = &m->m_body[m->m_len - 2];
  2489. X        if (PrefChar(*cp))
  2490. X            m->m_len -= 2;
  2491. X        else if (commands[cp[1]].c_proc == Forget)
  2492. X            m->m_len -= 1;
  2493. X    } else
  2494. X        complain("[end-kbd-macro: not currently defining macro!]");
  2495. X}
  2496. X
  2497. void
  2498. ExecMacro()
  2499. X{
  2500. X    do_macro(&KeyMacro);
  2501. X}
  2502. X
  2503. void
  2504. MacInter()
  2505. X{
  2506. X    extern int    Interactive;
  2507. X
  2508. X    if (!Asking)
  2509. X        return;
  2510. X    Interactive = 1;
  2511. X}
  2512. X
  2513. int
  2514. ModMacs()
  2515. X{
  2516. X    register struct macro    *m;
  2517. X
  2518. X    for (m = macros->m_nextm; m != 0; m = m->m_nextm)
  2519. X        if (m->m_flags & SAVE)
  2520. X            return YES;
  2521. X    return NO;
  2522. X}
  2523. X
  2524. data_obj *
  2525. findmac(prompt)
  2526. char    *prompt;
  2527. X{
  2528. X    char    *strings[100];
  2529. X    register char    **strs = strings;
  2530. X    register int    com;
  2531. X    register struct macro    *m = macros;
  2532. X
  2533. X    for (; m != 0; m = m->m_nextm)
  2534. X        *strs++ = m->Name;
  2535. X    *strs = 0;
  2536. X
  2537. X    if ((com = complete(strings, prompt, NOTHING)) < 0)
  2538. X        return 0;
  2539. X    m = macros;
  2540. X    while (--com >= 0)
  2541. X        m = m->m_nextm;
  2542. X    return (data_obj *) m;
  2543. X}
  2544. X
  2545. void
  2546. DelMacro()
  2547. X{
  2548. X    struct macro    *m;
  2549. X
  2550. X    if ((m = (struct macro *) findmac(ProcFmt)) == 0)
  2551. X        return;
  2552. X    if (m == &KeyMacro)
  2553. X        complain("[It's illegal to delete the keyboard-macro!]");
  2554. X    del_mac(m);
  2555. X}
  2556. END_OF_FILE
  2557. if test 7870 -ne `wc -c <'./macros.c'`; then
  2558.     echo shar: \"'./macros.c'\" unpacked with wrong size!
  2559. fi
  2560. # end of './macros.c'
  2561. fi
  2562. echo shar: End of archive 3 \(of 21\).
  2563. cp /dev/null ark3isdone
  2564. MISSING=""
  2565. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  2566.     if test ! -f ark${I}isdone ; then
  2567.     MISSING="${MISSING} ${I}"
  2568.     fi
  2569. done
  2570. if test "${MISSING}" = "" ; then
  2571.     echo You have unpacked all 21 archives.
  2572.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2573. else
  2574.     echo You still need to unpack the following archives:
  2575.     echo "        " ${MISSING}
  2576. fi
  2577. ##  End of shell archive.
  2578. exit 0
  2579.